package com.project_doctor.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.project_doctor.pojo.Conversation;
import com.project_doctor.pojo.Doctor;
import com.project_doctor.pojo.Message;
import com.project_doctor.service.ConversationService;
import com.project_doctor.service.DoctorService;
import com.project_doctor.service.MessageService;
import com.project_doctor.mapper.MessageMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
/**
* @author 龙龙与贝儿
* @description 针对表【t_message】的数据库操作Service实现
* @createDate 2025-06-07 11:22:51
*/
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message>
    implements MessageService{


    private static final String MESSAGE_KEY_PREFIX = "message:";
    private static final String CONVERSATION_MESSAGES_KEY_PREFIX = "conversation_messages:";
    private static final long MESSAGE_EXPIRE_DAYS = 7;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    ConversationService conversationService;
    @Autowired
    private DoctorService doctorService;

    @Override
    @Transactional
    public Message saveMessage(Message message) {
        // 生成雪花ID
        Snowflake snowflake = IdUtil.createSnowflake(1, 1);
        Long id = snowflake.nextId();
        message.setId(id);
        message.setMessageTime(new Date());
        message.setIsRead(0);
        // 获取并缓存Doctor信息
        Doctor sender = doctorService.getUserById(message.getSenderId());
        message.setSender(sender); // 嵌套存储完整Doctor

        // 保存消息到Redis
        String messageKey = MESSAGE_KEY_PREFIX + id;
        redisTemplate.opsForValue().set(messageKey, JSON.toJSONString(message), MESSAGE_EXPIRE_DAYS, TimeUnit.DAYS);

        // 将消息ID添加到对话的消息列表
        String conversationMessagesKey = CONVERSATION_MESSAGES_KEY_PREFIX + message.getConversationId();
        redisTemplate.opsForZSet().add(conversationMessagesKey, String.valueOf(id), id);
        // 设置对话消息列表的过期时间（确保与消息一致）
        redisTemplate.expire(conversationMessagesKey, MESSAGE_EXPIRE_DAYS, TimeUnit.DAYS);

        // 添加到接收者的未读集合
        Conversation conversation = conversationService.getConversationById(message.getConversationId());
        String unreadKey="";
        if (conversation.getStarterId().equals(message.getSenderId())) {
            unreadKey = "unread:" + conversation.getParticipantId()+ ":conv:" + message.getConversationId();
        }else {
            unreadKey = "unread:" + conversation.getStarterId()+ ":conv:" + message.getConversationId();
        }
        redisTemplate.opsForSet().add(unreadKey, String.valueOf(message.getId()));

        // 更新对话的最新消息
        conversationService.updateLatestMessage(message.getConversationId(),message);

        return message;
    }

    @Override
    public List<Message> getMessagesByConversationId(Long conversationId) {
        String conversationMessagesKey = CONVERSATION_MESSAGES_KEY_PREFIX + conversationId;
        // 获取该对话下的所有消息ID（按ID升序排列）
        Set<String> messageIds = redisTemplate.opsForZSet().range(conversationMessagesKey, 0, -1);

        if (messageIds == null || messageIds.isEmpty()) {
            return Collections.emptyList();
        }

        List<Message> messages = new ArrayList<>();
        // 批量获取消息内容
        for (String messageId : messageIds) {
            String messageKey = MESSAGE_KEY_PREFIX + messageId;
            String messageJson = redisTemplate.opsForValue().get(messageKey);
            if (messageJson != null) {
                Message message = JSON.parseObject(messageJson, Message.class);
                messages.add(message);
            }
        }
        return messages.stream()
                .map(this::processMessageWithDoctor)
                .collect(Collectors.toList());
    }

    private Message processMessageWithDoctor(Message message) {
        // 检查嵌套的Doctor是否存在（可能因缓存过期丢失）
        if (message.getSender() == null && message.getSenderId() != null) {
            // 从二级缓存或数据库获取
            message.setSender(doctorService.getUserById(message.getSenderId()));
        }
        return message;
    }




    @Override
    public void markAsReadBatch(Long conversationId, Long userId) {
        String conversationMessagesKey = CONVERSATION_MESSAGES_KEY_PREFIX + conversationId;
        Set<String> messageIds = redisTemplate.opsForZSet().range(conversationMessagesKey, 0, -1);

        if (messageIds != null && !messageIds.isEmpty()) {
            // 使用 Redis Pipeline 批量更新消息
            redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
                StringRedisConnection stringConnection = (StringRedisConnection) connection;

                for (String messageId : messageIds) {
                    String messageKey = MESSAGE_KEY_PREFIX + messageId;

                    // 1. 获取原始JSON
                    String json = stringConnection.get(messageKey);
                    if (json != null) {
                        try {
                            // 2. 解析JSON并修改isRead字段
                            JSONObject jsonObject = JSON.parseObject(json);
                            jsonObject.put("isRead", 1);
                            String updatedJson = jsonObject.toJSONString();

                            // 3. 更新回Redis
                            stringConnection.set(messageKey, updatedJson);
                        } catch (Exception e) {
                            log.error("Failed to parse message JSON for ID: {}"+messageId, e);
                        }
                    }
                }
                return null;
            });
        }

        // 从 Redis 中移除已读消息
        String unreadKey = "unread:" + userId + ":conv:" + conversationId;
        redisTemplate.delete(unreadKey);
    }

    // 从 Redis 中获取最新一条消息
    @Override
    public Message getLatestMessage(Long conversationId) {
        String conversationMessagesKey = CONVERSATION_MESSAGES_KEY_PREFIX + conversationId;

        // 获取有序集合中最后一个元素（最新消息ID）
        Set<String> latestMessageIds = redisTemplate.opsForZSet().reverseRange(conversationMessagesKey, 0, 0);

        if (latestMessageIds == null || latestMessageIds.isEmpty()) {
            return null;
        }

        String latestMessageId = latestMessageIds.iterator().next();
        String messageKey = MESSAGE_KEY_PREFIX + latestMessageId;

        // 获取最新消息的 JSON 字符串
        String messageJson = redisTemplate.opsForValue().get(messageKey);

        if (messageJson != null) {
            Message message = JSON.parseObject(messageJson, Message.class);
            return processMessageWithDoctor(message);
        }

        return null;
    }

    @Override
    public Integer calculateUnreadCount(Long conversationId, Long userId) {
        String unreadKey = "unread:" + userId + ":conv:" + conversationId;
        Long count = redisTemplate.opsForSet().size(unreadKey);
        return count != null ? count.intValue() : 0;
    }


}




